
package net.biaji.alephclient;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

class JslibAgent extends LibAgent {

    protected static String baseurl = "http://opac.jslib.org.cn/F/";

    /**
     * 详细格式 (950)
     */
    public static final String LIST_TYPE_DETAIL = "950";

    /**
     * 简明表格(000)
     */
    public static final String LIST_TYPE_SIMPLE = "000";

    /**
     * 封面格式(998)
     */
    public static final String LIST_TYPE_FRONT_PAGE = "998";

    /**
     * 标准格式(999)
     */
    public static final String DETAIL_TYPE_STANDARD = "999";

    /**
     * 卡片格式
     */
    public static final String DETAIL_TYPE_CARD = "037";

    /**
     * 引文格式
     */
    public static final String DETAIL_TYPE_QOUTE = "040";

    /**
     * 字段名格式
     */
    public static final String DETAIL_TYPE_SEG = "002";

    @Override
    public boolean login(String name, String password) {
        String loginUrl = appendGetParm(baseurl, "bor_id", name);
        loginUrl = appendGetParm(loginUrl, "bor_verification", password);
        loginUrl = appendGetParm(loginUrl, Commands.CMD_FUNCTION, Commands.CMD_FUNCTION_LOGIN);
        loginUrl = appendGetParm(loginUrl, "login_source", "bor-info");
        loginUrl = appendGetParm(loginUrl, "bor_library", Commands.PARAM_LIB_NANJING);
        String result = getContent(loginUrl);
        if (result.contains("我的基本信息")) {
            Document doc = Jsoup.parse(result);
            Element link = doc.select("a[title=退出系统]").first();
            if (link != null) {
                String linkStr = link.attr("href");
                sessionID = extractSessionId(linkStr);
                if (sessionID != null)
                    JslibAgent.baseurl = JslibAgent.baseurl + sessionID;
            }
            isLogin = true;
            return true;
        } else
            return false;
    }

    @Override
    public ArrayList<Book> searchByName(String bookName) {
        ArrayList<Book> result = searchByCommand("WRD=(" + bookName + ")");
        return result;
    }

    @Override
    public ArrayList<Book> searchByCommand(String command) {
        ArrayList<Book> result = null;
        setOption(JslibAgent.baseurl);
        String findUrl = appendGetParm(JslibAgent.baseurl, Commands.CMD_FUNCTION,
                Commands.CMD_FUNCTION_SEARCH_ADV);
        findUrl = appendGetParm(findUrl, Commands.CMD_PARM_KEY_TERM, command);
        findUrl = appendGetParm(findUrl, "adjacent", "N");
        findUrl = appendGetParm(findUrl, "local-base", Commands.PARAM_LIB_NANJING_CHI);
        String resultPage = getContent(findUrl);
        result = parseBookList(LIST_TYPE_FRONT_PAGE, resultPage);
        return result;
    }

    @Override
    // TODO:添加更多详情。目前因懒得处理多作者，所以就这样吧。最后应该以字段格式取所有数据
    // 具体到查询结果时，可用func=full-set-set_body&set_number=031331&set_entry=000001&format=037来取一部书的内容
    public Book getBook(String sn) {
        Book aBook = null;
        String url = appendGetParm(JslibAgent.baseurl + "-01234", Commands.CMD_FUNCTION,
                Commands.CMD_FUNCTION_SEARCH);
        url = appendGetParm(url, "find_code", "SYS");
        url = appendGetParm(url, "request", sn);
        String resultPage = getContent(url).replaceAll("&nbsp;", "");
        Document doc = Jsoup.parse(resultPage);
        Element bookInfo = doc.select("div#details2").first();

        // Elements jsonInfo = doc.select("script[src~=/cgi-bin/alkb.cgi.*]");

        if (bookInfo == null)
            return aBook;

        HashMap<String, String> elements = new HashMap<String, String>();
        Elements trs = bookInfo.select("tr");
        for (Element tr : trs) {
            elements.put(tr.select("td:eq(0)").text(), tr.select("td:eq(1)").text().trim());
        }

        aBook = new Book();
        aBook.setSN(sn);
        aBook.setName(elements.get("题名").split(":")[0]);
        aBook.setISBN(elements.get("ISBN").split(":")[0].replaceAll("-", ""));
        aBook.setStandardNum(elements.get("馆藏"));
        aBook.addAuthor(elements.get("个人著者"));
        aBook.setPublisher(elements.get("出版发行"));
        aBook.setDescribe(elements.get("载体形态").split(":")[0]);
        aBook.setPrice(elements.get("ISBN").split(":")[1]);

        return aBook;
    }

    /**
     * 设置获取查询页面的结果格式
     * 
     * @param baseurl
     */
    private void setOption(String baseurl) {
        String setOptionUrl = appendGetParm(baseurl, Commands.CMD_FUNCTION, "option-update");
        setOptionUrl = appendGetParm(setOptionUrl, "file_name", Commands.CMD_FUNCTION_SEARCH);
        setOptionUrl = appendGetParm(setOptionUrl, "SHORT_NO_LINES", "50");
        setOptionUrl = appendGetParm(setOptionUrl, "P_SUB_LIBRARY", "");
        setOptionUrl = appendGetParm(setOptionUrl, "SHORT_FORMAT", LIST_TYPE_FRONT_PAGE);
        setOptionUrl = appendGetParm(setOptionUrl, "SCAN_INCLUDE_AUT", "N");
        setOptionUrl = appendGetParm(setOptionUrl, "UPDATE_PROFILE", "N");
        getContent(setOptionUrl);
    }

    /**
     * 由页面解析图书列表
     * 
     * @param listType
     * @param pageContent
     * @return
     */
    private ArrayList<Book> parseBookList(String listType, String pageContent) {
        if (listType == null || listType.length() == 0)
            return null;

        ArrayList<Book> result = new ArrayList<Book>();

        if (listType.equals(LIST_TYPE_SIMPLE)) {
        } else if (listType.equals(LIST_TYPE_DETAIL)) {
        } else if (listType.equals(LIST_TYPE_FRONT_PAGE)) {
            long time = System.currentTimeMillis();
            Document doc = Jsoup.parse(pageContent);
            System.out.println("Parse consume:" + (System.currentTimeMillis() - time) / 1000 + "s");
            Elements books = doc.select(".items");
            for (Element bookItem : books) {
                Book book = new Book();

                book.setSN(extractDocNumber(bookItem.toString()));
                book.setName(bookItem.select(".itemtitle > a").text());
                book.addAuthor(bookItem.select("tbody table").select("tr:eq(0)").select("td:eq(1)")
                        .text());
                book.setStandardNum(bookItem.select("tbody table").select("tr:eq(0)")
                        .select("td:eq(3)").text());
                book.setPubDate(bookItem.select("tbody table").select("tr:eq(1)")
                        .select("td:eq(3)").text());
                // 封面获取。根据脚本索引构建列表，作为参数传入alkb.cgi?id=xxxxx 返回json中有对应key如下
                // covers({'NJL01000249898':'06daee','NJL01000116384':'0bbefd','NJL01000514670':'001940'})
                // 根据获得的key 由/cgi-bin/alkb.cgi?id2=xxx获得对应封面
                // String coverUrl =
                // bookItem.select(".cover > a > img[src]").text();
                // if (coverUrl != null && !coverUrl.contains("nocover")) {
                // book.setCoverUrl(coverUrl);
                // }

                result.add(book);
            }
        } else {
            result = null;
        }
        return result;
    }

    @Override
    public ArrayList<Book> getBookInPocket() throws NotLoginException {
        if (!isLogin)
            throw new NotLoginException();

        ArrayList<Book> result = new ArrayList<Book>();
        String url = appendGetParm(baseurl, Commands.CMD_FUNCTION,
                Commands.CMD_FUNCTION_CURRENT_STATUS);
        Document doc = Jsoup.parse(getContent(url));
        Elements books = doc.select("center>center>table[border] tr");

        for (int i = 1; i < books.size(); i++) {
            Element book = books.get(i);
            Book abook = new Book();
            abook.setSN(extractDocNumber(book.select("td:eq(10) a").attr("href")));
            abook.addAuthor(book.select("td:eq(2)").text());
            abook.setName(book.select("td:eq(3)").text());
            abook.setPubDate(book.select("td:eq(4)").text());
            abook.setReturnDateExpected(book.select("td:eq(5)").text());
            String fine = book.select("td:eq(6)").text();
            abook.setFine(fine.length() == 0 ? 0 : Float.parseFloat(fine));
            abook.setStandardNum(book.select("td:eq(8)").text());
            result.add(abook);
        }
        return result;
    }

    @Override
    public ArrayList<Book> getHistory() {
        ArrayList<Book> result = new ArrayList<Book>();
        String historyUrl = appendGetParm(baseurl, Commands.CMD_FUNCTION,
                Commands.CMD_FUNCTION_BORROW_HISTORY);
        String history = getContent(historyUrl);
        Document doc = Jsoup.parse(history);
        Elements books = doc.select("center table").get(1).select("tr");
        for (int i = 1; i < books.size(); i++) {
            Element bookItem = books.get(i);

            Book book = new Book();
            book.addAuthor(bookItem.select("td:eq(1)").text());
            book.setName(bookItem.select("td:eq(2)").text());
            book.setPubDate(bookItem.select("td:eq(3)").text());
            book.setReturnDateExpected(bookItem.select("td:eq(4)").text());
            book.setReturnDate(bookItem.select("td:eq(6)").text());

            book.setFine(bookItem.select("td:eq(8)").text() == null
                    || bookItem.select("td:eq(8)").text().length() == 0 ? 0 : Float
                    .parseFloat(bookItem.select("td:eq(8)").text()));

            result.add(book);
        }

        return result;
    }

    private String extractSessionId(String url) {
        Matcher matcher = Pattern.compile("http://opac.jslib.org.cn:80/F/(.*)-.*").matcher(url);
        return matcher.find() ? matcher.group(1) : null;
    }

    /**
     * 由字串中提取docNumber
     * 
     * @param content 包含格式为doc_number=XXX字样的内容
     * @return 相应的docNumber
     */
    private String extractDocNumber(String content) {
        Matcher matcher = Pattern.compile(".*doc_number=([0-9]{9}).*").matcher(content);
        return matcher.find() ? matcher.group(1) : null;
    }

    @Override
    public void reserve(String docNum) throws NotLoginException {
        if (!isLogin)
            throw new NotLoginException();

    }

    @Override
    /*
     * 暂时简单实现。理论上可用。未经任何安全检查与处理。TODO:检查当前docNum合法性/续借结果
     */
    public void extend(String docNum) throws NotLoginException {
        if (!isLogin)
            throw new NotLoginException();
        String extendUrl = appendGetParm(baseurl, Commands.CMD_FUNCTION,
                Commands.CMD_FUNCTION_RENEW);
        extendUrl = appendGetParm(extendUrl, "doc_number", docNum);
        extendUrl = appendGetParm(extendUrl, "item_sequence", "000030"); // 具体作用不明
        extendUrl = appendGetParm(extendUrl, Commands.CMD_PARM_KEY_ADMIN_LIB,
                Commands.PARAM_LIB_NANJING);
        getContent(extendUrl);
    }

}
